use std::env;
use std::path::PathBuf;
use std::process::Command;

fn main() {
    let out_path = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR must be set"));

    cmake::Config::new("").build();
    println!(
        "cargo:rustc-link-search=native={}",
        out_path.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=CppSide");

    let bindings = bindgen::Builder::default()
        .header("cpp_side.h")
        .clang_arg(&format!("-I{}", get_llvm_dir().join("include").display()))
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .blocklist_type("MlirContext")
        .blocklist_type("MlirValue")
        .blocklist_type("wchar_t")
        .blocklist_type("max_align_t")
        .generate()
        .expect("Unable to generate bindings");
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

fn get_llvm_dir() -> PathBuf {
    let llvm_config = env::var("LLVM_CONFIG").unwrap_or_else(|_| "llvm-config".to_string());
    let output = Command::new(&llvm_config).arg("--prefix").output().expect(
        "Failed to execute llvm-config. Ensure LLVM is installed and llvm-config is in PATH",
    );
    if !output.status.success() {
        panic!(
            "llvm-config failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
    }
    let llvm_dir = PathBuf::from(String::from_utf8(output.stdout).unwrap().trim());
    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
    println!(
        "cargo:rustc-link-search=native={}",
        llvm_dir.join("lib").display()
    );
    llvm_dir
}
